logo头像
Snippet 博客主题

React Native之轻量级存储AsyncStorage

本文于447天之前发表,文中内容可能已经过时。

AsyncStorage是一个简单的、异步的、持久化的以键值对形式进行数据存储的存储系统,对于App来说是全局性的。它的作用等价于iOS的NSUserDefaluts或Android的SharedPreferences,使用AsyncStorage用来替换老旧的LocalStorage。

方法

它有很多方法,每一个方法都有回调函数,第一个参数是错误对象,错了就是展示错误信息,否则为null。都会返回一个Promise对象。

  • static getItem(key:string , callback:(error,result)):
    根据键来获取值,获取的结果会在回调函数中。
  • static setItem(key:string , value:string , callback:(error)): 设置键值对。
  • static removeItem(key:string , callback:(error)): 将根据键移出一项
  • static mergeItem:(key:string , value:string , callback:(error)):
    合并现有的值和输入值。
  • static clear(callback:(error)): 清除所有的项目。
  • static getAllKeys(callback:(error)): 获取所有的键。
  • static multiGet(keys,callback:(errors,result)):获取多项,其中keys是字符串数组。
  • static
    multiSet(keyValuePairs,callback:(errors)):设置多项,其中keyValuePairs是字符串的二维数组。
  • static multiRemove(keys,callback(errors)):删除多项,其中keys是字符串数组。
  • static multiMerge(keyValuePairs,callback:(errors)):多个键值合并,其中keyValuePairs是字符串中的二维数组。

示例

简单存储:

1
2
3
4
5
6
7
setData(text){
AsyncStorage.setItem(AsyncStorageKey,text,()=>{
this.setState({
data:text,
});
});
}

注意:可以设置一个回调,设置成功后,调用回调,修改状态机变量。

删除指定的KEY值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
delData(){
// 读取key字段并将结果作为第二个参数传递给callback。 如果有任何错误发生,则会传递一个Error对象作为第一个参数。返回一个Promise对象。
AsyncStorage.getItem(AsyncStorageKey,(error,text)=>{
if(text=== null ){
alert(AsyncStorageKey +"没有对应的值");
}else{
//删除数据
AsyncStorage.removeItem(AsyncStorageKey,()=>{
this.setState({
data:"",
},()=>{
alert('删除成功');
});
});
}
});
}

完整代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
import React, { Component } from 'react';
import {
StyleSheet,
View,
Text,
TouchableHighlight,
Dimensions,
AsyncStorage
} from 'react-native';
const {width, height} = Dimensions.get('window');
var data = "";
const AsyncStorageKey = "AS_";
export default class AsyncStorageExample extends Component {
constructor(props) {
super(props);
this.state = {
data:""
};
}
setData(text){
AsyncStorage.setItem(AsyncStorageKey,text,()=>{
this.setState({
data:text,
});
});
}
delData(){
// 读取key字段并将结果作为第二个参数传递给callback。
// 如果有任何错误发生,则会传递一个Error对象作为第一个参数。返回一个Promise对象。
AsyncStorage.getItem(AsyncStorageKey,(error,text)=>{
if(text=== null ){
alert(AsyncStorageKey +"没有对应的值");
}else{
//删除数据
AsyncStorage.removeItem(AsyncStorageKey,()=>{
this.setState({
data:"",
},()=>{
alert('删除成功');
});
});
}
});
}
render() {
return (
<View style={styles.container}>
<TouchableHighlight style={styles.itemView} underlayColor="red" onPress={this.setData.bind(this,"我是小刀")}>
<Text style={styles.itemText}>
1、存储数据
</Text>
</TouchableHighlight>
<TouchableHighlight style={styles.itemView} underlayColor="red" onPress={this.delData.bind(this)}>
<Text style={styles.itemText}>
2、删除数据
</Text>
</TouchableHighlight>
<Text style={{paddingTop:40}}>
AsyncStorage存储的值是:{this.state.data}
</Text>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#f2f2f2',
paddingTop:20,
},
itemView:{
backgroundColor:'grey',
height:44,
width:width,
justifyContent:'center',
marginTop:10,
},
itemText:{
fontSize:15,
color:'#ffffff',
textAlign:'left',
marginLeft:20,
},
});

购物车结算示例

这里写图片描述
示例代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
var React = require('react-native');
var Dimensions = require('Dimensions');
var {
AppRegistry,
StyleSheet,
Text,
View,
Image,
ScrollView,
WebView,
NavigatorIOS,
AsyncStorage,
TouchableOpacity,
} = React;
var Model = [
{
id: '1',
title:'商品1',
desc:'哎哟~不错哦',
price: 10000,
url:'http://ww4.sinaimg.cn/thumb180/4d7f0a6dgw1f18crfemfog20b405mqv7.gif'
},
{
id: '2',
title:'商品2',
desc:'哎哟~不错哦2',
price: 10330,
url:'http://ww3.sinaimg.cn/thumb180/6aa09e8fgw1f18abnz36mg20b30697wj.gif'
},
{
id: '3',
title:'商品3',
desc:'哎哟~不错3',
price: 100003,
url:'http://ww4.sinaimg.cn/thumb180/6298156bgw1f18ydrmj4cj20hi0bhq5r.jpg'
},
{
id: '4',
title:'商品4',
desc:'哎哟~不错哦4',
price: 100004,
url:'http://ww1.sinaimg.cn/thumb180/a5d15efdgw1f18k8pu0cyj20jg0jbdja.jpg'
},
{
id: '5',
title:'商品5',
desc:'哎哟~不错哦5',
price: 100005,
url:'http://ww2.sinaimg.cn/thumb180/005yYQOngw1f18lqh7hx9j326r1gincv.jpg'
},
{
id: '6',
title:'商品6',
desc:'哎哟~不错哦6',
price: 100006,
url:'http://ww2.sinaimg.cn/thumb180/5ba8d1cbgw1f18hhiaj3jj21kw1kw10x.jpg'
}
];
var styles = StyleSheet.create({
container : {
flex: 1
},
row : {
flexDirection: 'row',
marginBottom: 10,
},
item : {
flex: 1,
marginLeft:5,
borderWidth: 1,
borderColor: '#ddd',
marginRight: 5,
height: 100,
},
img: {
flex: 1,
backgroundColor: 'transparent',
},
item_text: {
backgroundColor: '#000',
opacity:0.7,
color:'#fff',
height:25,
lineHeight:18,
textAlign:'center',
marginTop:74
},
btn: {
backgroundColor: '#ff7200',
height: 33,
textAlign : 'center',
color: '#fff',
marginLeft:10,
marginRight: 10,
lineHeight: 24,
marginTop: 40,
fontSize: 18,
},
list_item : {
marginLeft: 5,
marginRight: 5,
padding:5 ,
borderWidth: 1,
height: 30,
borderRadius: 3,
borderColor: '#ddd',
},
list_item_desc : {
flex: 2,
fontSize: 15,
},
list_item_price: {
flex: 1,
textAlign: 'right',
fontSize: 15,
},
clear: {
marginTop : 10,
backgroundColor: '#fff',
color: '#000',
borderColor: '#ddd',
borderWidth:1,
marginLeft: 10,
marginRight:10,
lineHeight: 24,
height:33,
fontSize: 18,
textAlign: 'center',
}
});
//列表项组件
var Item = React.createClass({
render:function(){
return(
<View style = {styles.item}>
<TouchableOpacity onPress = {this.props.press}>
<Image
resizeMode = 'contain'
style = {styles.img}
source = {{uri:this.props.url}}>
<Text numberLines = {1} style = {styles.item_text}>
{this.props.title}
</Text>
</Image>
</TouchableOpacity>
</View>
);
}
});
//列表组件
var List = React.createClass({
getInitialState: function(){
return{
count: 0
};
},
componentDidMount: function() {
var _that = this;
AsyncStorage.getAllKeys(function(err,keys){
if (err) {
//TODO:存储取数据出错 ,给用户提示错误信息。
}
//将存储的商品条数反应到按钮上
_that.setState({
count:keys.length
});
});
},
render: function(){
var list = [];
for(var i in Model){
if (i % 2 ===0) {
var row = (
<View style = {styles.row} key = {i}>
<Item url={Model[i].url}
title = {Model[i].title}
press = {this.press.bind(this,Model[i])}></Item>
<Item url = {Model[parseInt(i) + 1].url}
title = {Model[parseInt(i) + 1].title}
press = {this.press.bind(this,Model[parseInt(i) + 1])}></Item>
</View>
);
list.push(row);
}
}
var counts = this.state.count;
var str = null;
if (counts) {
str = ',共'+counts+'件商品';
}
return(
<ScrollView style = {{marginTop:10}}>
{list}
<Text onPress = {this.goGouWu} style = {styles.btn}>
去结算{str}
</Text>
</ScrollView>
);
},
//前往购物车方法
goGouWu: function(){
this.props.navigator.push({
component:GouWu,
title: '购物车'
});
},
//商品被选中方法
press: function(data){
var count = this.state.count;
count++;
//改变数字状态
this.setState({
count: count
});
//AsyncStorage 存储
AsyncStorage.setItem('SP-'+this.genId() + '-SP',JSON.stringify(data),function(err){
if (err) {
//TODO:存储出错
}
});
},
genId: function(){
return 'xxxxxxx-xxxx-2xxxx-bxxxxxxxxx'.replace(/[xy]/g,function(c){
var r = Math.random() * 16|0,
v = c == 'x'?r:(r & 0x3 | 0x8);
return v.toString(16);
}).toUpperCase();
}
});
var GouWu = React.createClass({
getInitialState:function(){
return{
data:[],
price:0
};
},
render:function(){
var data = this.state.data;
var price = this.state.price;
var list = [];
for(var i in data){
price += parseFloat(data[i].price);
list.push(
<View style = {[styles.row,styles.list_item]} key = {i}>
<Text style = {styles.list_item_desc} >
{data[i].title}
{data[i].desc}
</Text>
<Text style = {styles.list_item_price} >${data[i].price}</Text>
</View>
);
}
var str = null;
if (price) {
str = ',共'+ price.toFixed(1)+'元'
}
return(
<ScrollView style = {{marginTop:10}}>
{list}
<Text style = {styles.btn} onPress = {this.paySuccess}>支付{str}</Text>
<Text style = {styles.clear} onPress = {this.clearStorage}>清空购物车</Text>
</ScrollView>
)
},
componentDidMount: function() {
var _that = this;
AsyncStorage.getAllKeys(function(err,keys){
if (err) {
//TODO:存储取数据出错
//如果发生错误,这里直接返回(return)防止进入下面的逻辑
}
AsyncStorage.multiGet(keys,function(errs,result){
//TODO:错误处理
//得到的结果是二维数组
//result[i][0]表示我们存储的键,result[i][1]表示我们存储的值
var arr = [];
for(var i in result){
arr.push(JSON.parse(result[i][1]));
}
_that.setState({
data:arr
});
});
})
},
clearStorage:function(){
var _that = this;
AsyncStorage.clear(function(err){
if (!err) {
_that.setState({
data:[],
price:0,
});
alert('购物车已经清空')
}
//TODO:err
});
},
paySuccess: function(){
var _that = this;
AsyncStorage.clear(function(err){
if (!err) {
alert("支付成功!")
_that.props.navigator.pop();
}
//TODO:err
});
_that.setState({
data:[],
price:0,
count:0,
str:'去结算'
});
}
});
var wxsPrj = React.createClass({
render: function() {
return (
<NavigatorIOS style = {styles.container}
initialRoute = {
{
component:List,
title:'商品列表',
}
}/>
);
}
});
AppRegistry.registerComponent('wxsPrj', () => wxsPrj);

代码说明:
首先我们来看一下模块, 我们创建Model(数据源) styles(样式列表) Item(列表项组件) List(列表组件) GouWu(购物车组件)
前三个没有什么好说的,先来说一下List组件:
在List组件中,我们用Model数据源来渲染列表项。使用i%2 ==0 来控制,每两个列表项目在一行中。
在press方法中我们让count+1,并且使用AsynStorage.setItem将选中的商品数据添加到App本地存储中。这里之所以使用SP-为前缀,-SP为后缀,采用GUID为存储的键名的一部分,是为了区分其他数据,好处:

可以缺粉用户数据,例如username信息。
可以放置key重复,保证同名商品都能被添加进购物车。
这样我们就把商品信息存储起来了。

我们在componentDidMount方法中作了一个处理,在用户第二次进入的时候,如果没有支付,依旧会告诉用户购物车中的商品数。使用Asy ncStorage.getAllKeys获取数据的条数,
在去结算按钮中,我们注册了点击方法goGouWu事件。使用this.props.navigator.push将购物车组件加载。

支付宝打赏 微信打赏

如果文章对你有帮助,欢迎点击上方按钮打赏作者

上一篇